package com.bestom.communication.activity;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.res.Resources;
import android.database.Cursor;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ScrollView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.bestom.communication.R;
import com.bestom.communication.ThisApplication;
import com.bestom.communication.callbacks.IGetMessageCallBack;
import com.bestom.communication.constants.FilesConstant;
import com.bestom.communication.services.MQTTService;
import com.bestom.communication.sql.DbHelper;
import com.bestom.communication.sql.DbManage;
import com.bestom.communication.ui.SwipeAdapter;
import com.bestom.communication.utils.SharedPreferencesUtil;
import com.suke.widget.SwitchButton;

import java.util.ArrayList;

public class MainActivity extends BaseActivity implements IGetMessageCallBack {

    private Context mContext;
    private MQTTService mqttService = null;
    private MyServiceConnection serviceConnection;

    private ScrollView mScrollView;
    private TextView receiveText;
    private ImageView statusImage;
    private TextView statusText;
    private Spinner publishSpinner;
    private ArrayAdapter<String> mArrayAdapter;
    private EditText sendEdit;
    private SwitchButton timingSend;

    private AlertDialog publishDialog;
    private SwipeAdapter publishAdapter;
    private AlertDialog subscribeDialog;
    private SwipeAdapter subscribeAdapter;
    private EditText topicEditText;

    /**当前程序保存订阅和推送主题的列表
     * 1、 initData中初始化
     * 2、 查询之前保存在数据库中的数据添加进列表
     * 3、 之后的添加和删除逻辑
     * */
    private ArrayList<String> subscribeArrayList;
    private ArrayList<String> publishArrayList;
    /**
     * auto = true 用于判断是否仅更新UI不做逻辑
     * */
    private boolean auto;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = this;
        initData();
        initView();
        startMQttService();
    }

    private void initView() {

        //数据接收区组件
        mScrollView = findViewById(R.id.scrollView);
        receiveText = findViewById(R.id.receive_text);
        //连接状态图标及文字组件
        statusImage = findViewById(R.id.status_img);
        statusText = findViewById(R.id.status_text);
        //定时发送组件及监听事件
        timingSend = findViewById(R.id.timing_send);
        timingSend.setOnCheckedChangeListener((view, isChecked) -> {
            if (auto) return;
            if (mqttService != null && mqttService.mqttIsConnect()){
                if (isChecked){
                    mHandler.postDelayed(mRunnable,ThisApplication.getApplication().getTime() * 1000);
                }else {
                    mHandler.removeCallbacks(mRunnable);
                }
            }else {
                Toast.makeText(getApplicationContext(),"请先连接 MQtt", Toast.LENGTH_SHORT).show();
                mHandler.removeCallbacks(mRunnable);
                mHandler.sendEmptyMessage(2);
            }
        });
        //连接MQtt SwitchButton按钮组件及监听事件
        SwitchButton connectSwitchButton = findViewById(R.id.connect_mqtt);
        connectSwitchButton.setOnCheckedChangeListener((view, isChecked) -> {
            if (isChecked){
                String address = (String) SharedPreferencesUtil.getInstance().getValue(FilesConstant.mMqttAddressPref,FilesConstant.mDefaultMqttAddress);
                String port = (String) SharedPreferencesUtil.getInstance().getValue(FilesConstant.mPortPref,FilesConstant.mDefaultPort);
                String clientId = (String) SharedPreferencesUtil.getInstance().getValue(FilesConstant.mClientIdPref,FilesConstant.mDefaultClientId);
                String username = (String) SharedPreferencesUtil.getInstance().getValue(FilesConstant.mUsernamePref,FilesConstant.mDefaultUsername);
                runOnUiThread(() -> {
                    statusText.setText("正在连接");
                    statusImage.setImageResource(R.drawable.off);
                });
                String password = (String) SharedPreferencesUtil.getInstance().getValue(FilesConstant.mPasswordPref,FilesConstant.mDefaultPassword);
                connectMQtt("tcp://" + address + ":" + port, clientId, username, password);
            }else {
                timingSend.setChecked(false);
                disConnectMQtt();
                runOnUiThread(() -> {
                    statusText.setText("未连接");
                    statusImage.setImageResource(R.drawable.off);
                });

            }
        });
        //下拉框选择推送主题组件
        publishSpinner = findViewById(R.id.publish_spinner);
        mArrayAdapter = new ArrayAdapter<>(this, R.layout.support_simple_spinner_dropdown_item, publishArrayList);
        publishSpinner.setAdapter(mArrayAdapter);
        //输入框组件
        sendEdit = findViewById(R.id.send_edit);
        //加载一个输入框组件，用于添加订阅或推送主题时
        View view = getLayoutInflater().inflate(R.layout.edit_text_view, null);
        topicEditText = view.findViewById(R.id.edit_text);
        //发送按钮及监听事件
        findViewById(R.id.send).setOnClickListener(v -> {
            Object item = publishSpinner.getSelectedItem();
            if (item == null) Toast.makeText(getApplicationContext(),"推送主题不能为空",Toast.LENGTH_SHORT).show();
            else publish(publishSpinner.getSelectedItem().toString(),sendEdit.getText().toString());
        });
        //清空按钮
        findViewById(R.id.clear_send).setOnClickListener(v -> sendEdit.setText(""));
        findViewById(R.id.clear_receive).setOnClickListener(v -> receiveText.setText(""));
        //右上角推送主题弹出框布局及监听事件
        View view1 = getLayoutInflater().inflate(R.layout.publish_dialog_topic, null);
        RecyclerView publishTopicShow = view1.findViewById(R.id.publish_topic_show);
        publishTopicShow.setLayoutManager(new LinearLayoutManager(this));
        publishAdapter = new SwipeAdapter(mContext, DbHelper.PUBLISH_NAME, publishArrayList, topicEditText);
        publishTopicShow.setAdapter(publishAdapter);

        AlertDialog.Builder publishBuilder = new AlertDialog.Builder(mContext);
        TextView title1 = new TextView(mContext);
        title1.setText("推送主题");
        title1.setPadding(40, 40, 40, 40);
        title1.setTextSize(20);
        publishBuilder.setCustomTitle(title1);
        publishBuilder.setView(view1);
        publishBuilder.setPositiveButton("添加", (dialog, which) -> addDialog(DbHelper.PUBLISH_NAME));
        publishBuilder.setNegativeButton("取消", null);
        publishDialog = publishBuilder.create();
        //右上角订阅主题弹出框布局及监听事件
        View view2 = getLayoutInflater().inflate(R.layout.subscribe_dialog_topic, null);
        RecyclerView subscribeTopicShow = view2.findViewById(R.id.subscribe_topic_show);
        subscribeTopicShow.setLayoutManager(new LinearLayoutManager(this));
        subscribeAdapter = new SwipeAdapter(mContext, DbHelper.SUBSCRIBE_NAME, subscribeArrayList, topicEditText);
        subscribeTopicShow.setAdapter(subscribeAdapter);

        AlertDialog.Builder subscribeBuilder = new AlertDialog.Builder(mContext);
        TextView title2 = new TextView(mContext);
        title2.setText("订阅主题");
        title2.setPadding(40, 40, 40, 40);
        title2.setTextSize(20);
        subscribeBuilder.setCustomTitle(title2);
        subscribeBuilder.setView(view2);
        subscribeBuilder.setPositiveButton("添加", (dialog, which) -> addDialog(DbHelper.SUBSCRIBE_NAME));
        subscribeBuilder.setNegativeButton("取消", null);
        subscribeDialog = subscribeBuilder.create();
    }

    /**添加主题弹出框*/
    private void addDialog(String table) {
        ViewGroup parent = (ViewGroup) topicEditText.getParent();
        if (parent != null) parent.removeView(topicEditText);
        new AlertDialog.Builder(this)
                .setTitle("添加主题")
                .setView(topicEditText)
                .setPositiveButton("确定", (dialog, which) -> save(table, topicEditText.getText().toString()))
                .setNegativeButton("取消", null)
                .show();
    }

    /**保存添加的主题*/
    private void save(String table, String topic) {

        if (topic.isEmpty()){
            Toast.makeText(getApplicationContext(),"不能添加空主题", Toast.LENGTH_SHORT).show();
            return;
        }

        if (table.equals(DbHelper.SUBSCRIBE_NAME)) {
            if (subscribeArrayList.contains(topic)){
                Toast.makeText(getApplicationContext(),"当前主题已存在，请检查", Toast.LENGTH_SHORT).show();
                return;
            }
            subscribeArrayList.add(topic);
            //添加订阅主题之后调用MQtt 订阅
            subscribe(topic);
            //订阅主题添加之后，通知更新一下，不然右上角订阅主题布局里的内容不改变
            subscribeAdapter.notifyDataSetChanged();
        }else {
            if (publishArrayList.contains(topic)){
                Toast.makeText(getApplicationContext(),"当前主题已存在，请检查", Toast.LENGTH_SHORT).show();
                return;
            }
            publishArrayList.add(topic);
            updateView("推送主题：" + topic + ", 添加成功");
            //订阅主题添加之后，通知更新一下，不然推送主题下拉框布局里的内容不改变
            mArrayAdapter.notifyDataSetChanged();
            //推送主题添加之后，通知更新一下，不然右上角推送主题布局里的内容不改变
            publishAdapter.notifyDataSetChanged();
        }
        //保存进数据库
        DbManage.getInstance(mContext).addRecord(table, topic);
    }

    /**初始化数据*/
    private void initData() {
        subscribeArrayList = new ArrayList<>();
        publishArrayList = new ArrayList<>();
        Cursor cursor1 = DbManage.getInstance(mContext).select(DbHelper.PUBLISH_NAME);
        while (cursor1.moveToNext()){
            publishArrayList.add(cursor1.getString(cursor1.getColumnIndex("topic")));
        }
        cursor1.close();
        Cursor cursor2 = DbManage.getInstance(mContext).select(DbHelper.SUBSCRIBE_NAME);
        while (cursor2.moveToNext()){
            subscribeArrayList.add(cursor2.getString(cursor2.getColumnIndex("topic")));
        }
        cursor2.close();
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {

        if (item.getItemId() == R.id.set) startActivity(new Intent(MainActivity.this, SettingActivity.class));
        else if (item.getItemId() == R.id.subscribe){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) subscribeDialog.show();
        } else if (item.getItemId() == R.id.publish) publishDialog.show();
        else if(item.getItemId() == android.R.id.home){
            new AlertDialog.Builder(this)
                    .setTitle("关闭应用")
                    .setMessage("确定要退出此应用吗？")
                    .setPositiveButton("确定", (dialog, which) -> finish())
                    .setNegativeButton("取消", null)
                    .show();
        }
        return super.onOptionsItemSelected(item);
    }

    /**绑定 MQtt服务，暂未连接MQtt*/
    private void startMQttService(){

        serviceConnection = new MyServiceConnection();
        Intent intent = new Intent(mContext, MQTTService.class);
        bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
    }

    /**停止 MQtt服务*/
    private void stopMQttService(){
        if (serviceConnection != null){
            unbindService(serviceConnection);
            serviceConnection = null;
        }
    }
    /**连接 MQtt*/
    private void connectMQtt(String host, String clientId, String username, String password){
        if (mqttService != null) mqttService.connectionMQtt(host,clientId,username,password,this);
    }
    /**断开 MQtt*/
    private void disConnectMQtt(){
        if (mqttService != null) mqttService.disConnectMQtt();
    }
    /**订阅 MQtt主题*/
    private void subscribe(String topic){
        if (mqttService != null) mqttService.subscribe(topic);
    }
    /**推送 MQtt信息*/
    private void publish(String topic, String msg){
        if (mqttService != null) mqttService.publish(topic,msg);
    }

    /**连接成功 MQtt 回调*/
    @Override
    public void setSuccess(String str1) {
        runOnUiThread(() -> {
            statusText.setText("已连接");
            statusImage.setImageResource(R.drawable.on);
        });
        updateView(str1);
        for (String topic : subscribeArrayList){
            subscribe(topic);
        }
    }
    /**连接失败 MQtt 回调*/
    @Override
    public void setFail(String str1) {
        runOnUiThread(() -> {
            statusText.setText("尝试连接中...");
            statusImage.setImageResource(R.drawable.off);
        });
    }
    /**MQtt 信息回调*/
    @Override
    public void setMessage(String str1) {
        updateView(str1);
    }

    /**绑定服务的 ServiceConnection*/
    class MyServiceConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            mqttService = ((MQTTService.CustomBinder)iBinder).getService();
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mqttService = null;
        }
    }

    /**更新数据接收区*/
    private void updateView(String info) {
        Message message = new Message();
        message.what = 1;
        message.obj = info;
        mHandler.sendMessage(message);
    }

    @SuppressLint("HandlerLeak")
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 1) {
                receiveText.append(msg.obj + "\n");
                scrollToBottom(receiveText);
            }else if (msg.what == 2){
                auto = true;
                timingSend.setChecked(false);
                auto = false;
            }
        }
    };

    /**定时发送 MQtt*/
    private final Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            Object item = publishSpinner.getSelectedItem();
            if (item == null) Toast.makeText(getApplicationContext(),"推送主题不能为空",Toast.LENGTH_SHORT).show();
            else publish(item.toString(),sendEdit.getText().toString());
            mHandler.postDelayed(this, ThisApplication.getApplication().getTime() * 1000);
        }
    };

    /**自动滚动数据接收区*/
    private void scrollToBottom(final View view) {

        if (mScrollView == null || view == null) return;
        runOnUiThread(() -> {
            int offset = view.getMeasuredHeight() - mScrollView.getMeasuredHeight();
            if (offset < 0) offset = 0;
            //scrollview Start rolling
            mScrollView.scrollTo(0, offset);
        });
    }

    @Override
    protected void onDestroy() {
        stopMQttService();
        super.onDestroy();
    }
}